/**
**************************************************************************************
*Founder Effect                                                                      *
*Copyright (C) 2006-2007, 5d Studios (www.5d-Studios.com)                            *
*                                                                                    *
*This library is free software; you can redistribute it and/or                       *
*modify it under the terms of the GNU Lesser General Public                          *
*License as published by the Free Software Foundation; either                        *
*version 2.1 of the License, or (at your option) any later version.                  *
*                                                                                    *
*This library is distributed in the hope that it will be useful,                     *
*but WITHOUT ANY WARRANTY; without even the implied warranty of                      *
*MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU                   *
*Lesser General Public License for more details.                                     *
*                                                                                    *
*You should have received a copy of the GNU Lesser General Public                    *
*License along with this library; if not, write to the Free Software                 *
*Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA      *
**************************************************************************************
*/
#pragma once
#include "Myriad.h"
#include "Timer.h"

/**
 * Buffer ids
 */
enum {
    BUFFER_CONSOLE
};


/**
==========================
The Heart of the MyriadEngine
The kernel decides which process runs, and
holds all subsystems
==========================
*/
class Kernel
{
public:
    Kernel(void);

    /** Init the kernel */
    int Init();
    /** Shutdown all Processes */
    void Shutdown();
    /** Run the kernel */
    void Execute();

    /** Add a process */
	void AddProcess(IProcess* p);
    /** Suspend a process */
	void SuspendProcess(IProcess* p);
    /** Resume a process */
	void ResumeProcess(IProcess* p);
    /** Remove a process */
	void RemoveProcess(IProcess* p);
    /** Kill all the processes */
	void KillAll();

    /** Get the current time */
    float GetTime();
    /** Get the time between last frame and the current one */
    float GetFrameTime();
    /** Timer object */
    Timer& GetTimer() { return m_percisionTimer; };

    /**
     *   Retrieve a subsystem
     */

    /** The Input System */
    IInput* GetInput() { return m_input; };
    /** Sound System */
    ISound* GetSound() { return m_sound; };
    /** The Renderer System */
    IRenderManager* GetRenderer() { return m_renderer; };
    /** Scripting Engine System */
    IScriptEngine* GetScriptEngine() { return m_scripter; };
    /** The game System */
    GameManager* GetGame() { return m_game; };
    /** Resource Manager System */
    IResourceManagement* GetResource() { return m_resource; };
    
    /** Console subsystem */
    Console* GetConsole() { return &m_console; };
    /** Cvar System */
    Cvars* GetCvars() { return &m_cvars; };

    /** Useful functions */

    /** Print to console */
    void Printf( const char *s, ... );
    /** Log and print to console */
    void LPrintf( const char *s, ... );

    /**
    =========================
    Add the subsystems
    =========================
    */

    /** Set the Engines Scripting System */
    void SetScriptEngine(IScriptEngine* s) {
        m_scripter = s;
    };

    /** Set the Engines Input System */
    void SetInput(IInput* in) {
        AddProcess( in );
        m_input = in;
    };
    /** Set the Engines Game Management System */
    void SetGame(GameManager* g) {
        AddProcess( g );
        m_game = g;
    };
    /** Set the Engines Rendering Management System */
    void SetRenderer( IRenderManager* r) {
        AddProcess( r );
        m_renderer = r;
    };
    /** Set the Engines Sound System */
    void SetSound( ISound* s) {
        AddProcess( s );
        m_sound = s;
    };
    /** Set the VFS */
    void SetResourceManagement( IResourceManagement* r ) {
        m_resource = r;
    };
public:
    virtual ~Kernel(void);

private:
    /** Run a Frame */
    void Frame();

    // active list
    typedef std::list< IProcess* > type_ProcessList;
    type_ProcessList m_runningProcesses;
    type_ProcessList m_pausedProcesses;

    // Input System
    IInput*          m_input;
    // Rendering Backend
    IRenderManager*  m_renderer;
    // Sound System
    ISound*          m_sound;
    // Scripting System
    IScriptEngine*   m_scripter;
    // Game Management
    GameManager*     m_game;
    // Resource Management
    IResourceManagement* m_resource;
    // Console - print debug info, exec commands
    Console  m_console;
    // console variables, ingame dynamic variables
    Cvars    m_cvars;

    float   m_lastFrame;
    float   m_delta;
    float   m_nextTick;
    // keep the application going
    bool    m_quit;
    // High performance timer
    Timer   m_percisionTimer;
};

